#include "io/io.h"
#include "disk.h"
#include "memory/memory.h"
#include "config.h"
#include "status.h"

struct disk disk; 

const int disk_read_sector(const int lba, const int total, void* buf)
{
    unsigned short* ptr = 0; 
    char c = 0; 
    int j; 
    int i; 

    outb(0x1F6, (lba >> 24) | 0xE0); 
    outb(0x1F2, total);
    outb(0x1F3, (unsigned char)(lba & 0xFF)); 
    outb(0x1F4, (unsigned char)(lba >> 8)); 
    outb(0x1F5, (unsigned char)(lba >> 16)); 
    outb(0x1F7, 0x20); // ATA command matrix: 0x20 = Read Sectors With Retry

    ptr = (unsigned short*)buf; 
    for (j = 0; j < total; j++) {
        // Wait for the buffer to be ready
        do {
            c = insb(0x1F7); 
        }
        while (!(c & 0x08));

        // read by two bytes
        for (i = 0; i < 256; i++) { // is 256 a magic number?
            *ptr = insw(0x1F0); 
            ptr++; 
        }
    } 

    return 0; 
}

void disk_search_and_init()
{
    // Temporary implementation
    memset(&disk, 0, sizeof(disk)); 
    disk.type = TESTOS_DISK_TYPE_REAL; 
    disk.sector_size = TESTOS_SECTOR_SIZE; 
    disk.id = 0; 
    disk.filesystem = fs_resolve(&disk); 
}

struct disk* disk_get(const int index)
{
    // Temporary implementation
    if (index != 0) {
        return 0; 
    }

    return &disk; 
}

const int disk_read_block(struct disk* idisk, const unsigned int lba, const int total, void* buf) 
{
    // Temporary implementation 
    if (idisk != &disk) {
        return -TESTOS_STATUS_IO_ERROR; 
    }

    return disk_read_sector(lba, total, buf); 
}